package com.michaelbulava.TFS.vcs.internal;

import com.intellij.openapi.vcs.FilePath;
import com.microsoft.tfs.core.clients.versioncontrol.soapextensions.ExtendedItem;
import com.microsoft.tfs.core.clients.versioncontrol.soapextensions.ItemType;
import com.microsoft.tfs.core.clients.versioncontrol.soapextensions.PendingChange;
import com.sun.corba.se.spi.activation.Server;

/**
 * Created by mbulava on 5/7/2015.
 */
public abstract class ServerStatus {

    public final int localVersion;
    public final int itemId;
    public final boolean isDirectory;
    public final String sourceItem;
    public final String targetItem;
    private final boolean IsLocalWorkspace;

    public final boolean IsLocalWorkspace(){
        return this.IsLocalWorkspace;
    }

    protected ServerStatus(int localVer, int itemId, boolean isDirectory, String sourceItem, String targetItem,
                           boolean localWorkspace) {
        this.localVersion = localVer;
        this.itemId = itemId;
        this.isDirectory = isDirectory;
        this.sourceItem = sourceItem;
        this.targetItem = targetItem;
        this.IsLocalWorkspace = localWorkspace;
    }

    protected ServerStatus(boolean isLocalWorkspace){
        localVersion = -1;
        itemId = -1;
        this.isDirectory = false;
        this.sourceItem = null;
        this.targetItem = null;
        this.IsLocalWorkspace = isLocalWorkspace;
    }

    protected ServerStatus(PendingChange pendingChange, boolean localWorkspace){
        this(pendingChange.getVersion(), pendingChange.getItemID(),
                (pendingChange.getItemType() == ItemType.FOLDER),
                pendingChange.getSourceLocalItem(), pendingChange.getServerItem(), localWorkspace);
    }

    protected ServerStatus(ExtendedItem extendedItem, boolean localWorkspace){
        this(extendedItem.getLocalVersion(), extendedItem.getItemID(),
                (extendedItem.getItemType() == ItemType.FOLDER),
                extendedItem.getLocalItem(), extendedItem.getTargetServerItem(), localWorkspace);
    }

    protected ServerStatus(FilePath file){
        localVersion = -1;
        itemId = -1;
        this.isDirectory = file.isDirectory();
        this.sourceItem = file.getPath();
        this.targetItem = null;
        this.IsLocalWorkspace = true;
    }

    @Override
    public String toString(){
        return getClass().getName().substring(getClass().getName().lastIndexOf("$") + 1);
    }
    
    public final void visitBy(FilePath filePath, boolean existLocally, StatusVisitor statusVisitor){
        if (filePath == null)
            throw new IllegalArgumentException("filePath cannot be null");
        if (statusVisitor == null)
            throw new IllegalArgumentException("statusVisitor cannot be null");
        performVisitBy(filePath, existLocally, statusVisitor);
    }

    protected abstract void performVisitBy(FilePath filePath, boolean existsLocally, StatusVisitor statusVisitor);

    /*
    public static final ChangeType NONE = new ChangeType(0, _ChangeType._ChangeType_Flag.None.toString(), false);
    public static final ChangeType ADD = new ChangeType(2, _ChangeType._ChangeType_Flag.Add.toString(), false);
    public static final ChangeType EDIT = new ChangeType(4, _ChangeType._ChangeType_Flag.Edit.toString(), false);
    public static final ChangeType ENCODING = new ChangeType(8, _ChangeType._ChangeType_Flag.Encoding.toString(), false);
    public static final ChangeType RENAME = new ChangeType(16, _ChangeType._ChangeType_Flag.Rename.toString(), false);
    public static final ChangeType DELETE = new ChangeType(32, _ChangeType._ChangeType_Flag.Delete.toString(), false);
    public static final ChangeType UNDELETE = new ChangeType(64, _ChangeType._ChangeType_Flag.Undelete.toString(), false);
    public static final ChangeType BRANCH = new ChangeType(128, _ChangeType._ChangeType_Flag.Branch.toString(), false);
    public static final ChangeType MERGE = new ChangeType(256, _ChangeType._ChangeType_Flag.Merge.toString(), false);
    public static final ChangeType LOCK = new ChangeType(512, _ChangeType._ChangeType_Flag.Lock.toString(), false);
    public static final ChangeType ROLLBACK = new ChangeType(1024, _ChangeType._ChangeType_Flag.Rollback.toString(), true);
    public static final ChangeType SOURCE_RENAME = new ChangeType(2048, _ChangeType._ChangeType_Flag.SourceRename.toString(), true);
    public static final ChangeType TARGET_RENAME = new ChangeType(4096, "TargetRename", true);
    public static final ChangeType PROPERTY = new ChangeType(8192, _ChangeType._ChangeType_Flag.Property.toString(), true);
    public static final ChangeType ALL = new ChangeType(65535, "ALL", false);
    public static final ChangeType ADD_ENCODING = ADD.combine(ENCODING);
    public static final ChangeType ADD_EDIT_ENCODING = ADD.combine(EDIT).combine(ENCODING);
    public static final ChangeType RENAME_OR_DELETE = RENAME.combine(DELETE);
    public static final ChangeType ADD_BRANCH_OR_RENAME = ADD.combine(BRANCH).combine(RENAME);
    */


    public static class NotVersioned extends ServerStatus{
        public static final NotVersioned INSTANCE = new NotVersioned(); 
        
        private NotVersioned(){
            super(0, 0, false, null, null, false);
        }
        
        @Override
        protected void performVisitBy(FilePath filePath, boolean existsLocally, StatusVisitor statusVisitor) {
            statusVisitor.notVersioned(filePath, existsLocally, this);
        }
    }

    public static class Ignored extends ServerStatus{
        public static final Ignored INSTANCE = new Ignored();
        
        private Ignored(){
            super(0, 0, false, null, null, false);
        }

        @Override
        protected void performVisitBy(FilePath filePath, boolean existsLocally, StatusVisitor statusVisitor) {
            statusVisitor.ignored(filePath, existsLocally, this);
        }
    }


    public static class CheckedOutForEdit extends ServerStatus{

        protected CheckedOutForEdit(ExtendedItem extendedItem, boolean localWorkspace) {
            super(extendedItem, localWorkspace);
        }

        protected CheckedOutForEdit(PendingChange pendingChange, boolean localWorkspace) {
            super(pendingChange, localWorkspace);
        }

        @Override
        protected void performVisitBy(FilePath filePath, boolean existsLocally, StatusVisitor statusVisitor) {
            
            statusVisitor.checkedOutForEdit(filePath, existsLocally, this);
        }
    }

    public static class ScheduledForAddition extends ServerStatus{

        protected ScheduledForAddition(ExtendedItem extendedItem, boolean localWorkspace) {
            super(extendedItem, localWorkspace);
        }

        protected ScheduledForAddition(PendingChange pendingChange, boolean localWorkspace) {
            super(pendingChange, localWorkspace);
        }

        @Override
        protected void performVisitBy(FilePath filePath, boolean existsLocally, StatusVisitor statusVisitor) {
            
            statusVisitor.scheduledForAddition(filePath, existsLocally, this);
        }
    }

    public static class ScheduledForDeletion extends ServerStatus{

        protected ScheduledForDeletion(ExtendedItem extendedItem, boolean localWorkspace) {
            super(extendedItem, localWorkspace);
        }

        protected ScheduledForDeletion(PendingChange pendingChange, boolean localWorkspace) {
            super(pendingChange, localWorkspace);
        }

        @Override
        protected void performVisitBy(FilePath filePath, boolean existsLocally, StatusVisitor statusVisitor) {
            
            statusVisitor.scheduledForDeletion(filePath, existsLocally, this);
        }
    }

    public static class OutOfDate extends ServerStatus{
        private final ExtendedItem extendedItem;

        protected OutOfDate(ExtendedItem extendedItem) {
            super(extendedItem, false);
            this.extendedItem = extendedItem;
        }

        public ExtendedItem getExtendedItem(){
            return extendedItem;
        }

        @Override
        protected void performVisitBy(FilePath filePath, boolean existsLocally, StatusVisitor statusVisitor) {
            
            statusVisitor.outOfDate(filePath, existsLocally, this);
        }
    }

    public static class UpToDate extends ServerStatus{

        protected UpToDate(ExtendedItem extendedItem, boolean localWorkspace) {
            super(extendedItem, localWorkspace);
        }

        protected UpToDate(PendingChange pendingChange, boolean localWorkspace){
            super(pendingChange, localWorkspace);
        }

        protected UpToDate(boolean localWorkspace){
            super(localWorkspace);
        }

        @Override
        protected void performVisitBy(FilePath filePath, boolean existsLocally, StatusVisitor statusVisitor) {
            
            statusVisitor.upToDate(filePath, existsLocally, this);
        }
    }

    public static class Renamed extends ServerStatus{

        protected Renamed(ExtendedItem extendedItem, boolean localWorkspace) {
            super(extendedItem, localWorkspace);
        }

        protected Renamed(PendingChange pendingChange, boolean localWorkspace) {
            super(pendingChange, localWorkspace);
        }

        @Override
        protected void performVisitBy(FilePath filePath, boolean existsLocally, StatusVisitor statusVisitor) {
            
            statusVisitor.renamed(filePath, existsLocally, this);
        }
    }

    public static class RenamedCheckedOut extends ServerStatus{

        protected RenamedCheckedOut(ExtendedItem extendedItem, boolean localWorkspace) {
            super(extendedItem, localWorkspace);
        }

        protected RenamedCheckedOut(PendingChange pendingChange, boolean isLocalWorkspace) {
            super(pendingChange, isLocalWorkspace);
        }

        @Override
        protected void performVisitBy(FilePath filePath, boolean existsLocally, StatusVisitor statusVisitor) {
            
            statusVisitor.renamedCheckedOut(filePath, existsLocally, this);
        }
    }

    public static class Undeleted extends ServerStatus{

        protected Undeleted(ExtendedItem extendedItem, boolean localWorkspace) {
            super(extendedItem, localWorkspace);
        }

        protected Undeleted(PendingChange pendingChange, boolean localWorkspace) {
            super(pendingChange, localWorkspace);
        }

        @Override
        protected void performVisitBy(FilePath filePath, boolean existsLocally, StatusVisitor statusVisitor) {
            
            statusVisitor.undeleted(filePath, existsLocally, this);
        }
    }

    public static class WorkingFolder extends ServerStatus{

        public WorkingFolder(FilePath localFolder, String serverPath){
            super(-1, -1, true, localFolder.getPath(), serverPath, true);
        }

        @Override
        protected void performVisitBy(FilePath filePath, boolean existsLocally, StatusVisitor statusVisitor) {
            statusVisitor.WorkingFolder(filePath);
        }
    }

    public static class DisconnectedFile extends ServerStatus{

        protected DisconnectedFile(FilePath file) {
            super(file);
        }

        @Override
        protected void performVisitBy(FilePath filePath, boolean existsLocally, StatusVisitor statusVisitor) {
            statusVisitor.upToDate(filePath, existsLocally, this);
        }
    }

    public static class DisconnectedIgnoredFile extends ServerStatus{

        protected DisconnectedIgnoredFile(FilePath file) {
            super(file);
        }

        @Override
        protected void performVisitBy(FilePath filePath, boolean existsLocally, StatusVisitor statusVisitor) {
            statusVisitor.ignored(filePath, existsLocally, this);
        }
    }


}
